package com.guang.syncronized;

import com.guang.syncronized.domain.A;
import org.openjdk.jol.info.ClassLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * byte-----bit联系
 * 8bit = 1byte
 *
 * sync 修改了锁对象的内容——对象头
 *
 *      利用java参数：-XX:BiasedLockingStartupDelay=0  修改偏向延迟为0
 *
 *      测试对象的年龄的时候可以设置参数：-Xmx100m -Xms100m
 */
public class TestSyncExample {
    private final static Logger log = LoggerFactory.getLogger(TestSyncExample.class);

    A lock = new A();//偏向锁
    public static void main(String[] args) throws InterruptedException {
//        A lock = new A();//偏向锁
//        String s = ClassLayout.parseInstance(lock).toPrintablePretty(lock);
//        log.info(s);
//
//        List<D> list = new ArrayList<>();
//        for (int i = 0; i < 300; i++) {
//            list.add(new D());
//            log.info(ClassLayout.parseInstance(list.get(0)).toPrintablePretty(list.get(0)));
//        }

        new TestSyncExample().m1();
        // new TestSyncExample().m2();
    }


    public void m(){
        //非常希望这个加锁操作的效率很高
        //如果第一个线程来加锁 t1 效率很高---偏向锁
        //锁会膨胀会升级  t2来加锁 t1和t2 顺序执行
        //偏向的撤销 膨胀轻量锁
//        synchronized (lock) {
//            log.info("xxxx");
//            log.info("xxxx");
//            log.info("xxxx");
//        }

        //百分百确定这段代码的并发场景非常多
        //存在并发操作


    }


    public void testObjectlayout(){
        //lock 可偏向
//        synchronized (lock){//t1第一次
//            //判断lock是否可偏向
//            //是否已经偏向 否
//            //cas设置当前线程的id到对象头当中
//            //加锁成功 执行临界区的代码
//
//            //只有一次cas操作
//        }//对象头不会变  偏向t1
//
//        synchronized (lock){//t1 第二次加锁  偏向锁加锁
//            //判断是否可偏向
//            //判断当前线程id和对象头当中存的线程id是否相同
//            //如果相同则加锁成功 执行临界区的代码
//
//            //效率高 仅仅进行了一次线程id的比较
//        }
    }


    /**
     * 偏向锁 轻量锁 重量锁
     * 锁的膨胀 现象方面 不研究源码
     * 所得膨胀 源码方面 查看hotspot源码
     * @throws InterruptedException
     */
    public void m1() throws InterruptedException {
        Thread.currentThread().setName("main");
        log.info("----------关闭偏向延迟，默认是偏向锁101，但是没有偏向任何线程------------------------------------");
        log.info(ClassLayout.parseInstance(lock).toPrintable());        //偏向锁



        log.info("----------偏向锁已经偏向，101，偏向了某个线程id------------------------------------");        //偏向锁
        synchronized (lock){
            log.info(ClassLayout.parseInstance(lock).toPrintable());
        }

        TimeUnit.SECONDS.sleep(1);
        Thread t1= new Thread(() -> {
            log.info("----------其他线程来加锁（膨胀成为轻量锁）000 54 一个锁记录------------------------------------");        //轻量锁
            synchronized (lock) {
                log.info(ClassLayout.parseInstance(lock).toPrintable());
            }
        },"t1");

        t1.start();

        TimeUnit.SECONDS.sleep(1);

        Thread t2= new Thread(() -> {
            log.info("----------t2 和t1 顺序错开执行（依然轻量锁）没有竞争执行000 锁记录------------------------------------");        //轻量锁
            synchronized (lock) {
                log.info(ClassLayout.parseInstance(lock).toPrintable());
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t2");


        Thread t3= new Thread(() -> {
            log.info("----------t3加锁 t2没有释放 竞争执行（膨胀成为重量）010 62存的是ObjectMonitor对象的指针------------------------------------");        //轻量锁
            synchronized (lock) {
                log.info(ClassLayout.parseInstance(lock).toPrintable());
            }
        },"t3");

        t2.start();
        TimeUnit.MILLISECONDS.sleep(100);
        t3.start();

    }


    //hashCode 偏向锁
    public void m2(){
        lock.hashCode();
        log.info("----------关闭偏向延迟，默认是偏向锁101，但是没有偏向任何线程------------------------------------");
        log.info("----------由于计算了hashcode所以不能偏向，故而是001，没有偏向任何线程------------------------------------");
        log.info(ClassLayout.parseInstance(lock).toPrintable());        //偏向锁

        log.info("----------由于不可偏向，故而加锁直接膨胀成为轻量锁 000------------------------------------");        //偏向锁
        synchronized (lock){
            log.info(ClassLayout.parseInstance(lock).toPrintable());
        }
    }


    //锁的优化
    //锁消除
    public void m3(){
        Object o = new Object();
        synchronized (o){
            log.info("---------");
            log.info("---------");
            log.info("---------");
        }
    }

}
